package org.sdnstproject.interlayer.interlayerProxy;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.projectfloodlight.openflow.exceptions.OFParseError;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;

public class MsgHander implements Runnable {
	private static final Logger log = LoggerFactory.getLogger(MsgHander.class);
	public volatile boolean running = true;
	public LinkedHashMap<SwitchToInterlayer, InterlayerToController> pathLine;
	
	public MsgHander(LinkedHashMap<SwitchToInterlayer, InterlayerToController> pathLine) {
		this.pathLine = pathLine;
	}

	public synchronized String doMsgProxy() {
		Iterator<Entry<SwitchToInterlayer, InterlayerToController>> iterator = pathLine.entrySet().iterator();
		while(iterator.hasNext()) {
			Map.Entry<SwitchToInterlayer, InterlayerToController> entry = iterator.next();
			while(!entry.getKey().msgQueue.isEmpty()) {
				System.out.println("entry.getKey().msgQueue="+entry.getKey().msgQueue);
				ByteBuf bb = entry.getKey().msgQueue.pollFirst();
//				System.out.println("[InterlayerToController send:]"+OFMessageParse(bb).toString());
				if(bb != null) {
					entry.getValue().sendRawMsg(bb);
					
				}
			}
			while(!entry.getValue().msgQueue.isEmpty()) {
				System.out.println("entry.getValue().msgQueue="+entry.getValue().msgQueue);
				ByteBuf bb = entry.getKey().msgQueue.pollFirst();
//				System.out.println("[SwitchToInterlayer send:]"+OFMessageParse(bb).toString());
				if(bb != null) {
					entry.getKey().sendRawMsg(bb);
					
				}
			}
		}
		System.out.println("doMsgProxy=====================================");
		return "";
	}
	
	public OFFactory getOFMessageFactory(int version) {
		switch (version) {
	        case 1:
	            return OFFactories.getFactory(OFVersion.OF_10);
	        case 2:
	        	return OFFactories.getFactory(OFVersion.OF_11);
	        case 3:
	        	return OFFactories.getFactory(OFVersion.OF_12);
	        case 4:
	        	return OFFactories.getFactory(OFVersion.OF_13);
	        case 5:
	        	return OFFactories.getFactory(OFVersion.OF_14);
	        default:
	        	return OFFactories.getFactory(OFVersion.OF_10);
		}
	}
	
	public OFMessage OFMessageParse(ByteBuf bb) {
		int version = bb.readByte() + 0;
		OFFactory ofFactory = getOFMessageFactory(version);
		OFMessageReader<OFMessage> reader = ofFactory.getReader();
		OFMessage ofMessage = null;
		try {
			ofMessage = reader.readFrom(bb);
		} catch (OFParseError e) {
			e.printStackTrace();
		}
		return ofMessage;
	}

	@Override
	public void run() {
		System.out.println("MsgHander run...");
		try {
			while(running && !Thread.currentThread().isInterrupted()) {
				doMsgProxy();
				Thread.sleep(10);
	        }
        } catch (Exception e) {
        	Thread.currentThread().interrupt();
        	e.printStackTrace();
            log.info("[MsgHander] hand error!");
        }
		
	}
}
